Skip to content

test(node-http): halve headersTimeout in test-http-server-request-timeouts-mixed - #36563

Closed
robobun wants to merge 2 commits into
mainfrom
farm/d76355d5/http-timeouts-mixed-faster
Closed

robobun wants to merge 2 commits into
mainfrom
farm/d76355d5/http-timeouts-mixed-faster

Conversation

@robobun

@robobun robobun commented Jul 31, 2026 •

Copy link
Copy Markdown
Collaborator

What

test/js/node/test/sequential/test-http-server-request-timeouts-mixed.js is the upstream Node.js headersTimeout / requestTimeout interleave test. It was the slowest vendored sequential http test at ~12.5 s on the debian 13 x64-asan lane (build #86086).

Cause

The test schedules every write and every assertion at a multiple of headersTimeout (0.2x, 0.6x, 0.8x, 1.4x, 1.5x, 3.125x). Upstream sets the base to common.platformTimeout(2000), so the last callback fires at 3.125 * 2000 = 6.25 s on release lanes and 3.125 * 4000 = 12.5 s on debug builds where process.features.debug makes platformTimeout double its argument. On the CI asan lane (a release build with process.features.debug === false) the schedule is 6.25 s; the remaining ~6 s of the observed 12.5 s is LSAN / BUN_DESTRUCT_VM_ON_EXIT / validateExceptionChecks teardown the runner adds there.

Change

Lower the base to common.platformTimeout(1000). All delays scale with this value and connectionsCheckingInterval = headersTimeout / 8 scales with it too, so every relative margin is preserved. The narrowest window is request2's 408 arriving before the 1.4x checkpoint (0.075 * headersTimeout): 75 ms on every CI lane (all release, including asan), 150 ms on local debug builds.

The 408 status line and the common.mustCall(..., 4) / mustCallAtLeast / mustNotCall assertions are untouched, so coverage is the same as upstream; only the clock is compressed. Same pattern as sequential/test-performance-eventloopdelay.js (#33622).

test/expected-durations.json updated so shard bin-packing reflects the new cost until the next regeneration. The asan entry only drops from 12509 to ~9384 because the schedule halves (6250 -> 3125) but the per-process LSAN/VM-destruct teardown does not.

Verification

Local timing:

build before after
bun bd (debug+ASAN) 16.3 s 10.8 s
./build/debug/bun-debug 15.5 s 9.2 s
release+ASAN, CI runner env n/a 9.25 s

Stability at platformTimeout(1000):

config idle under CPU load
debug+ASAN (bun bd) 30/30 10/10 @ 8-way, 10/10 @ 14-way
release+ASAN + CI env* 30/30 20/20 @ 8-way

*BUN_JSC_validateExceptionChecks=1, BUN_JSC_dumpSimulatedThrows=1, BUN_DESTRUCT_VM_ON_EXIT=1, BUN_FEATURE_FLAG_NO_ORPHANS=1, LSAN enabled with test/leaksan.supp; the exact env scripts/runner.node.mjs sets for sequential/ on the asan lane.

Lower candidates were rejected: a fixed 800 ms base flakes 2/30 on the request2 window under debug+ASAN; 640 ms flakes 16/20.


no test proof · iteration 0 · docs-only change; test-proof not applicable

…eouts-mixed

Every delay in this upstream test is a ratio of headersTimeout, so
halving the base from platformTimeout(2000) to platformTimeout(1000)
preserves the relative schedule and all margins while halving wall
time. The tightest window (request2's 408 arriving before the 1.4x
checkpoint) is 0.075 * headersTimeout; platformTimeout keeps the debug
doubling so that stays >= 150 ms on debug/ASAN builds.

debug+ASAN, 30/30 pass idle, 10/10 under 8- and 14-way CPU load.
bun bd <file>: 16.3s -> 10.8s.
@coderabbitai

coderabbitai Bot commented Jul 31, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 91e4782e-96de-4e4d-9bb3-343508d77f45

📥 Commits

Reviewing files that changed from the base of the PR and between 37a7767 and 71f6793.

📒 Files selected for processing (2)
  • test/expected-durations.json
  • test/js/node/test/sequential/test-http-server-request-timeouts-mixed.js

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Jul 31, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 9:46 AM PT - Jul 31st, 2026

✅ @robobun, your commit 71f6793c02c1571963edd49e872f73cdb68da95a passed in Build #86355! 🎉


🧪   To try this PR locally:

bunx bun-pr 36563

That installs a local version of the PR into your bun-36563 executable, so you can run:

bun-36563 --bun

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — test-only timing compression that preserves all relative margins.

What was reviewed:

  • Traced every setTimeout multiplier (0.2x/0.6x/0.8x/1.4x/1.5x/3.125x) and connectionsCheckingInterval — all scale off headersTimeout, so halving the base preserves every ratio.
  • Verified the narrowest-window claim: request2's 408 lands by 1.2x + 0.125x = 1.325x vs the 1.4x checkpoint → 0.075x slack, i.e. 75 ms release / 150 ms debug via platformTimeout. Other windows (request1 headers 0.2x, request3/5 requestTimeout 0.4x+) are wider.
  • Confirmed no assertions/mustCall counts changed and the deviation-from-upstream comment matches repo convention.
Extended reasoning...

Overview

Single-constant change in a vendored Node.js sequential test: common.platformTimeout(2000) → common.platformTimeout(1000), plus a comment documenting the deviation from upstream and halved entries in test/expected-durations.json. No production code touched.

Security risks

None — test-only, no user-facing surface, no untrusted input.

Level of scrutiny

Low. This is a mechanical test-speed tweak following the same pattern as #33622 (test-performance-eventloopdelay.js). The only real risk is introducing flakiness by shrinking a timing window too far; the PR description addresses that head-on with 30/30 idle + 10/10 under-load runs and shows that lower candidates (800 ms fixed, 640 ms) do flake, which bounds the choice.

Other factors

I independently re-derived the timing schedule: request2 is opened at 0.2x, never sends the header terminator, so headersTimeout expires at 1.2x and the connections check (interval = 0.125x) closes it by 1.325x — leaving 0.075x before the 1.4x assertion. That matches the PR's narrowest-window analysis exactly. All other request paths (request1 completing headers at 0.8x before its 1.0x deadline; request3/4/5 requestTimeout deadlines vs the 3.125x final check) have ≥0.2x slack, so request2 is indeed the binding constraint. Retaining platformTimeout() keeps the debug/ASAN doubling, which is what makes the 150 ms figure hold on the slow lanes. The expected-durations.json edit is advisory bin-packing data that gets regenerated. The added comment is exactly the kind of "deliberate deviation from upstream" note REVIEW.md asks for.

…ation estimate

Self-review caught that the CI asan lane builds with --profile=ci-*
(buildType Release), so process.features.debug is false there and
platformTimeout does not double. Reworded the in-file comment to
state the 75 ms release window and the 150 ms debug-build window
separately, and corrected the asan expected-durations estimate (the
~6 s LSAN/validateExceptionChecks teardown on that lane is not halved
by the schedule change).

Verified on a local release+ASAN build with the same env the runner
sets (BUN_JSC_validateExceptionChecks=1, LSAN, BUN_DESTRUCT_VM_ON_EXIT,
BUN_FEATURE_FLAG_NO_ORPHANS): 30/30 idle and 20/20 under 8-way CPU
load at the new value.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — test-only timing constant change, halving the base headersTimeout in a vendored Node sequential test.

What was reviewed:

  • Traced all six setTimeout checkpoints (0.2x/0.6x/0.8x/1.4x/1.5x/3.125x) — every margin scales proportionally; narrowest window is request2's 408 before the 1.4x assert at 0.075x (75 ms release), matching the comment.
  • Confirmed platformTimeout in common/index.js:381 doubles on isDebug, so the comment's release-ASAN vs local-debug distinction is accurate.
  • expected-durations.json is advisory shard-packing metadata; values are plausible and regenerated periodically anyway.
Extended reasoning...

Overview

This PR touches two test-infrastructure files: it halves the headersTimeout base constant in test/js/node/test/sequential/test-http-server-request-timeouts-mixed.js from common.platformTimeout(2000) to common.platformTimeout(1000), adds a comment documenting the deviation from upstream Node and the narrowest timing window, and updates the corresponding entry in test/expected-durations.json to reflect the reduced wall-clock cost for CI shard bin-packing.

Security risks

None. No production code is touched — this is a vendored Node.js test file and a CI metadata JSON file.

Level of scrutiny

Low-to-moderate. The only real risk is introducing flakiness by shrinking timing windows too far. I re-derived the timing math for all five requests: request1 completes at 0.8x (0.6x margin before the 1.4x assert), request2's 408 must arrive by 1.4x after firing at worst 1.325x (0.075x = 75 ms release / 150 ms debug — the narrowest window, as stated), request3/5 time out at ~2.325x/2.725x with the final assert at 3.125x (≥0.4x margin), and request4 completes at 1.5x well before its 2.6x requestTimeout. All margins remain proportional because connectionsCheckingInterval = headersTimeout / 8 scales with the base. The PR description reports 30/30 idle passes plus 10/10 under 8-way and 14-way CPU load, and explicitly rejected lower values (800 ms, 640 ms) that flaked — exactly the empirical validation the review guidelines ask for when tightening test timing.

Other factors

The added comment satisfies the repo rule that a literal timing constant deviating from upstream needs a comment naming why. The expected-durations.json values are advisory and regenerated from CI periodically, so exact numbers don't need to be precise. The change follows the same precedent as #33622 (test-performance-eventloopdelay.js). No assertions, mustCall counts, or coverage were weakened — only the clock was compressed.

@robobun

robobun commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

The modified test passed on every lane across both CI builds (#86302 and #86355). The remaining reds are unrelated parallel-batch flakes (napi, spawn-streaming-stdout, streams-leak, html-rewriter-leak, tls-namedpipes, etc.) that also pass when re-run alone; none touch the two files in this diff. Ready for review.

@github-actions

Copy link
Copy Markdown
Contributor

Closing this PR because it has been inactive for more than 90 days.

@github-actions github-actions Bot closed this Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant